package com.doublefish.doublefishrobot.utils.ble;

import android.app.Application;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.location.LocationManager;
import android.os.Handler;
import android.util.Log;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.doublefish.doublefishrobot.R;
import com.doublefish.doublefishrobot.ui.home.bean.DeviceBean;
import com.doublefish.doublefishrobot.utils.AppCacheUtil;
import com.doublefish.doublefishrobot.utils.ToastUtil;
import com.doublefish.doublefishrobot.utils.ble.bean.ModeConstant;


import java.util.ArrayList;
import java.util.List;

/**
 * Created by peak on 2023/10/30
 */
public class DFBleManager {

    //第一枚蓝牙芯片 ATK-BLE01 主要用于超8
    private static String UUID_SERVER_1 = "d973f2e0-b19e-11e2-9e96-080020f29a66";
    private static String UUID_CHARREAD_1  = "d973f2e1-b19e-11e2-9e96-9e08000c9a66";
    private static String UUID_CHARWRITE_1 = "d973f2e2-b19e-11e2-9e96-0800200c9a66";

    //第二枚蓝牙芯片 ATK-BLE02 主要用于（自主）超8， 超6
    private static String UUID_SERVER_2 = "9ecadc24-0ee5-a9e0-93f3-a3b50100406e";
    private static String UUID_CHARREAD_2  = "9ecadc24-0ee5-a9e0-93f3-a3b50300406e";
    private static String UUID_CHARWRITE_2 = "9ecadc24-0ee5-a9e0-93f3-a3b50200406e";

    private Context context;
    private boolean didInitDFBleManager = false;

    //当前扫码到的设备列表
    private List<DeviceBean> deviceBeanList = new ArrayList<>();

    private boolean isScanning = false;  //是否正在扫描中

    private boolean didConnectBlueTooth = false; // 是否连接蓝牙
    private DeviceBean deviceBean;    //当前连接的设备
    private BleUUidBean uUidBean; //当前连接的蓝牙的uuid

    private OnBleManagerListner onBleManagerListner;

    private DFBleManager() {
    }

    private static volatile DFBleManager instance;

    public static DFBleManager getInstance() {
        if (instance == null) {
            synchronized (DFBleManager.class) {
                if (instance == null) {
                    instance = new DFBleManager();
                }
            }
        }
        return instance;
    }

    public void init(Application app, Context context) {
        if (didInitDFBleManager) {
            return;
        }
        if (app == null) {
            return;
        }
        if (context == null) {
            context = app.getApplicationContext();
        }
        if (context == null) {
            return;
        }
        this.context = context;
        //初始化
        didInitDFBleManager = true;
        BleManager.getInstance().init(app);
        BleManager.getInstance().enableLog(true);
        BleManager.getInstance().setReConnectCount(3);

        DFS8ProtocolManager.getInstance().initContext(context);
        DFS6ProtocolManager.getInstance().initContext(context);

//        UUID UUID_SERVER = UUID.fromString("d973f2e0-b19e-11e2-9e96-080020f29a66");
//        UUID[] serviceUuids = new UUID[1];
//        serviceUuids[0] = UUID_SERVER;

//        String[] names = new String[1];
//        names[0] = "1A:2B:3C";
//        names[0] = "DF-X8-1";
//        names[0] = "ATK-BLE03";

        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
//                .setServiceUuids(serviceUuids)      // 只扫描指定的服务的设备，可选
//                .setDeviceName(true, names)   // 只扫描指定广播名的设备，可选
                .setScanTimeOut(10000)              // 扫描超时时间，可选，默认10秒
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);
    }

    public DeviceBean getBleDeviceBean() {
        return deviceBean;
    }

    public void setOnBleManagerListner(OnBleManagerListner onBleManagerListner) {
        this.onBleManagerListner = onBleManagerListner;
    }

    public boolean curDeviceIsProtocolTypeS8() {
//        if (BuildConfig.DEBUG) {
//            return true;
//        }
        if (deviceBean == null) {
            return false;
        }
        return deviceBean.isProtocolTypeS8();
    }

    public boolean curDeviceIsProtocolTypeS6() {
//        if (BuildConfig.DEBUG) {
//            return true;
//        }
        if (deviceBean == null) {
            return false;
        }
        return deviceBean.isProtocolTypeS6();
    }

    //region 蓝牙扫描与连接

    //检查蓝牙权限
    public boolean canScan() {
        if (!BleManager.getInstance().isBlueEnable()) {
            ToastUtil.showToast(context, context.getString(R.string.no_open_ble));
            return false;
        }
        //蓝牙扫描 需要定位功能
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            ToastUtil.showToast(context, context.getString(R.string.ble_loction_alert));
            return false;
        }

        if (isScanning) {
            ToastUtil.showToast(context, context.getString(R.string.searching_ble_tips));
            return false;
        }
        return true;
    }

    //开始扫描蓝牙
    public void startBleScan() {
        if (!BleManager.getInstance().isBlueEnable()) {
            ToastUtil.showToast(context, context.getString(R.string.no_open_ble));
            return;
        }
        if (isScanning) {
            return;
        }
        isScanning = true;

        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                Log.i("onScanFinished", "onScanFinished");
                isScanning = false;
            }

            @Override
            public void onScanStarted(boolean success) {
                Log.i("onScanStarted", "onScanStarted");
                deviceBeanList.clear();
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                //默认名字为 超8：DF-X8-1  超6：DF-(XXX)  + 6位MAC
                String name = bleDevice.getName();
                if (name == null || name.length() < 7) {
                    return;
                }
                DeviceBean deviceBean = null;
                if (name.contains("DF-X8-")) {
                    //超级8代发球机
                    deviceBean = new DeviceBean();
                    deviceBean.setName(name);
                    deviceBean.setMac(bleDevice.getMac());
                    deviceBean.setDeviceType(ModeConstant.DeviceTypeS8);
                    deviceBean.setBleDevice(bleDevice);
                }
                else if (name.contains("DF-S6-")) {
                    //双鱼自己研发的发球机 目前只有超级6代发球机
                    deviceBean = new DeviceBean();
                    deviceBean.setName(name);
                    deviceBean.setMac(bleDevice.getMac());
                    deviceBean.setDeviceType(ModeConstant.DeviceTypeS6);
                    deviceBean.setBleDevice(bleDevice);
                }
                if (deviceBean == null) {
                    return;
                }
                deviceBeanList.add(deviceBean);
                if (onBleManagerListner != null) {
                    onBleManagerListner.onScanResult(deviceBeanList);
                }
            }
        });
    }

    //停止扫描蓝牙
    public void stopBleScan(){
        if (!isScanning) {
            return;
        }
        isScanning = false;
        BleManager.getInstance().cancelScan();
    }

    //监听特征值
    private void notifyBle() {
        if (uUidBean == null) {
            return;
        }
        BleManager.getInstance().notify(deviceBean.getBleDevice(), uUidBean.getService(), uUidBean.getRead(), new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                Log.i("onNotifySuccess ",  "onNotifySuccess");
                // onBleManagerListner.onConnectBle从 onConnectSuccess 中调整到这里
                if (onBleManagerListner != null) {
                    onBleManagerListner.onConnectBle(true, deviceBean);
                }
            }

            @Override
            public void onNotifyFailure(BleException exception) {
                Log.i("onNotifyFailure ",  exception.getDescription());
                if (onBleManagerListner != null) {
                    onBleManagerListner.onConnectBle(false, deviceBean);
                }
            }

            @Override
            public void onCharacteristicChanged(byte[] data) {
                Log.i("onCharacteristicChanged", "");
                //解包
                if (curDeviceIsProtocolTypeS8()) {
                    DFS8ProtocolManager.getInstance().unpack(data);
                } else if (curDeviceIsProtocolTypeS6()) {
                    DFS6ProtocolManager.getInstance().unpack(data);
                }
            }
        });
    }

    public void connectBt(DeviceBean deviceBean) {
        BleManager.getInstance().connect(deviceBean.getBleDevice(), new BleGattCallback() {
            @Override
            public void onStartConnect() {

            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                Log.i("onConnectFail", exception.getDescription());
                ToastUtil.showToast(context, context.getString(R.string.fail_ble));

                didConnectBlueTooth = false;
                uUidBean = null;
                AppCacheUtil.getInstance().setSynchronizedForRemote(false);
                if (onBleManagerListner != null) {
                    onBleManagerListner.onConnectBle(false,null);
                }
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                Log.i("onConnectSuccess", "onConnectSuccess");

                String service = null;
                String read = null;
                String write = null;
                //特征值
                List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService gattService : services) {
                    if (gattService.getUuid().toString().equals(UUID_SERVER_1)) {
                        service = UUID_SERVER_1;
                        read = UUID_CHARREAD_1;
                        write =UUID_CHARWRITE_1;

                        break;
                    } else if (gattService.getUuid().toString().equals(UUID_SERVER_2)) {
                        service = UUID_SERVER_2;
                        read = UUID_CHARREAD_2;
                        write = UUID_CHARWRITE_2;
                        break;
                    }
                }
                if (service == null) {
                    ToastUtil.showToast(context, context.getString(R.string.fail_ble_characteristic));
                    if (onBleManagerListner != null) {
                        onBleManagerListner.onConnectBle(false,null);
                    }
                    return;
                }

                ToastUtil.showToast(context, context.getString(R.string.success_ble));
                didConnectBlueTooth = true;
                DFBleManager.this.deviceBean = deviceBean;
                uUidBean = new BleUUidBean();
                uUidBean.setService(service);
                uUidBean.setWrite(write);
                uUidBean.setRead(read);
//                //监听特征值的变化
                notifyBle();
//                setMtu();

                //warning -- notifyBle是一个耗时操作，可能会导致 notify还没有完成，而在 onConnectBle中提前发送了指令
                // 将onBleManagerListner.onConnectBle 改到在 notifyBle的回调中
//                if (onBleManagerListner != null) {
//                    onBleManagerListner.onConnectBle(true,bleDeviceBean);
//                }
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                Log.i("onDisConnected", "");

                didConnectBlueTooth = false;
                uUidBean = null;
                AppCacheUtil.getInstance().setSynchronizedForRemote(false);
                if (onBleManagerListner != null) {
                    onBleManagerListner.onDisConnectBle();
                }
            }
        });
    }

    public void connectBt(int tId, String mac, String name, int deviceType) {
        if (!BleManager.getInstance().isBlueEnable()) {
            ToastUtil.showToast(context, context.getString(R.string.no_open_ble));
            return;
        }
        BleManager.getInstance().connect(mac, new BleGattCallback() {
            @Override
            public void onStartConnect() {
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                Log.i("onConnectFail", exception.getDescription());
                ToastUtil.showToast(context, context.getString(R.string.fail_ble));
                didConnectBlueTooth = false;
                uUidBean = null;
                AppCacheUtil.getInstance().setSynchronizedForRemote(false);

                if (onBleManagerListner != null) {
                    onBleManagerListner.onConnectBle(false, null);
                }
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                Log.i("onConnectSuccess", "onConnectSuccess");

                String service = null;
                String read = null;
                String write = null;
                //特征值
                List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService gattService : services) {
                    if (gattService.getUuid().toString().equals(UUID_SERVER_1)) {
                        service = UUID_SERVER_1;
                        read = UUID_CHARREAD_1;
                        write =UUID_CHARWRITE_1;

                        break;
                    } else if (gattService.getUuid().toString().equals(UUID_SERVER_2)) {
                        service = UUID_SERVER_2;
                        read = UUID_CHARREAD_2;
                        write = UUID_CHARWRITE_2;
                        break;
                    }
                }
                if (service == null) {
                    ToastUtil.showToast(context, context.getString(R.string.fail_ble_characteristic));
                    if (onBleManagerListner != null) {
                        onBleManagerListner.onConnectBle(false,null);
                    }
                    return;
                }

                DeviceBean deviceBean = new DeviceBean();
                deviceBean.setTid(tId);
                deviceBean.setName(name);
                deviceBean.setMac(bleDevice.getMac());
                deviceBean.setDeviceType(deviceType);
                deviceBean.setBleDevice(bleDevice);

                ToastUtil.showToast(context, context.getString(R.string.success_ble));
                didConnectBlueTooth = true;
                DFBleManager.this.deviceBean = deviceBean;
                uUidBean = new BleUUidBean();
                uUidBean.setService(service);
                uUidBean.setWrite(write);
                uUidBean.setRead(read);
//                //监听特征值的变化
                notifyBle();
//                setMtu();

                //warning -- notifyBle是一个耗时操作，可能会导致 notify还没有完成，而在 onConnectBle中提前发送了指令
                // 将onBleManagerListner.onConnectBle 改到在 notifyBle的回调中
//                if (onBleManagerListner != null) {
//                    onBleManagerListner.onConnectBle(true,bleDeviceBean);
//                }
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                Log.i("onDisConnected", "");
                didConnectBlueTooth = false;
                uUidBean = null;
                AppCacheUtil.getInstance().setSynchronizedForRemote(false);

                if (onBleManagerListner != null) {
                    onBleManagerListner.onDisConnectBle();
                }
            }
        });
    }

    public void disConnect() {
        if (didConnectBlueTooth && deviceBean.getBleDevice() != null) {
            if (curDeviceIsProtocolTypeS8()) {
                DFS8ProtocolManager.getInstance().disConnectMachine();
            } else if (curDeviceIsProtocolTypeS6()) {
                DFS6ProtocolManager.getInstance().disConnectMachine();
            }
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    BleManager.getInstance().disconnect(deviceBean.getBleDevice());
                }
            }, 100);
        }
    }

    public boolean isDidConnectBlueTooth() {
//        if (BuildConfig.DEBUG) {
//            return true;
//        }
        return didConnectBlueTooth;
    }

    public boolean isConnectToLastDevice() {
        if (deviceBean == null) {
            return false;
        }
        return BleManager.getInstance().isConnected(deviceBean.getMac());
    }

    public boolean canPostData() {
//        if (BuildConfig.DEBUG) {
//            return true;
//        }
        if (!BleManager.getInstance().isBlueEnable()) {
            return false;
        }
        return isDidConnectBlueTooth();
    }

    public void postData(byte[] bytes) {
        if (uUidBean == null) {
            return;
        }
        if (deviceBean == null) {
            return;
        }
        BleManager.getInstance().write(deviceBean.getBleDevice(), uUidBean.getService(), uUidBean.write, bytes, true, new BleWriteCallback() {
            @Override
            public void onWriteSuccess(int current, int total, byte[] justWrite) {
                Log.i("onWriteSuccess","current=" + current + "  total=" + total);
            }

            @Override
            public void onWriteFailure(BleException exception) {
                Log.i("onWriteFailure",exception.getDescription());
            }
        });
    }

    //监听特征值
    private void setMtu() {
        //这里mtu 的值与iOS对齐 取值185-3
        BleManager.getInstance().setMtu(deviceBean.getBleDevice(), 185, new BleMtuChangedCallback() {
            @Override
            public void onSetMTUFailure(BleException exception) {
                Log.e("onSetMTUFailure", exception.getDescription());
            }

            @Override
            public void onMtuChanged(int mtu) {
                Log.i("onMtuChanged", "mtu=" + mtu);
                //fixme mtu 比实际的 可用字节数要大3
                BleManager.getInstance().setSplitWriteNum(mtu - 3);

                DFS8ProtocolManager.getInstance().setSubPackSize(mtu - 3);
                DFS6ProtocolManager.getInstance().setSubPackSize(mtu - 3);

                //设置完mtu 开始监听特征值的变化
                notifyBle();
            }
        });
    }


    //endregion


    //region  listner
    public interface OnBleManagerListner {
        void onScanResult(List<DeviceBean> deviceBeanList);
        void onConnectBle(boolean success, DeviceBean deviceBean);
        void onDisConnectBle();
    }

    //endregion

    //蓝牙uuid
    private static class BleUUidBean {
        private String service;
        private String read;
        private String write;

        public String getService() {
            return service;
        }

        public void setService(String service) {
            this.service = service;
        }

        public String getRead() {
            return read;
        }

        public void setRead(String read) {
            this.read = read;
        }

        public String getWrite() {
            return write;
        }

        public void setWrite(String write) {
            this.write = write;
        }
    }
}
